package com.myk.game.gobangchess.rooms.oldrooms;

import com.myk.game.gobangchess.*;
import com.myk.game.gobangchess.rooms.absrooms.AbsMultiViewRoom;
import com.myk.game.gobangchess.rooms.absrooms.movechess.MoreColorCost;
import com.myk.game.gobangchess.signs.*;
import com.myk.game.gobangchess.utils.GridsUtils;

import java.util.ArrayList;
import java.util.List;

import static com.myk.game.gobangchess.constants.WinMode.*;

public class NanaBaroccoBWRoom extends AbsMultiViewRoom {

    private CacheSign cacheSign;
    List<Piece> pieceList = new ArrayList<>();
    Piece selectedTarget = null;
    public int zeroRemainBlack=4,zeroRemainWhite=4;

    public NanaBaroccoBWRoom(String roomName) {
        super(roomName, "七彩巴洛克青春版！", "黑白巴洛克", GridsUtils.createEmptyGrids(10, 10), false, false);
        initBoardStyle();
    }

    private void initBoardStyle(){
        List<Sign> chessboardStyle = new ArrayList<>();
        int row = curGrids.length;
        int col = curGrids[0].length;
        //绘制类似国际象棋的黑白相间的格子
        List<Integer> bGrids = new ArrayList<>();
        List<Integer> wGrids = new ArrayList<>();
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if ((i + j) % 2 == 0) {
                    bGrids.add(getIndex(i, j));
                }
                else {
                    wGrids.add(getIndex(i, j));
                }
            }
        }
        chessboardStyle.add(new ColorSign(bGrids, "#FF888888"));
        chessboardStyle.add(new ColorSign(wGrids, "#FFDDDDDD"));
        cacheSign = new CacheSign(this,"background",1,true,chessboardStyle);
    }

    @Override
    public String getRuleText() {
        return "[棋盘]\n" +
                "使用10x10的正方形格棋盘\n\n" +
                "[棋子]\n" +
                "数字0到9的棋子共100枚，双方各50枚\n开局前，所有棋子将被打乱并暗置在棋盘格上\n\n" +
                "[行动回合]\n" +
                "轮流行动，可选行动种类如下：\n（A）翻面一枚被暗置的棋子\n（B）控制一枚己方棋子走棋\n\n" +
                "[棋子走法]\n" +
                "移动：直向不超过<数字>格\n攻击：移动至敌人的位置，占位杀\n\n" +
                "[特殊规则]\n" +
                "（1）攻击比自己小且非因数的棋子时，占位吃子\n" +
                "（2）攻击为自己因数或倍数的棋子时，同归于尽\n" +
                "（3）攻击比自己大且非自己倍数的棋子时，自杀\n" +
                "（4）棋子0只能被对方非0明子中最小的棋子消灭\n" +
                "（5）未翻开暗子不可被吃，无法被任何效果影响\n\n" +
                "[胜负规则]\n" +
                "（A）落败条件：失去所有0\n（B）落败条件：无棋可走\n\n" +
                "更多信息请加设计师个人QQ群657062274了解。";
    }

    @Override
    public CacheSign getCacheSignByName(String cacheName) {
        return cacheSign;
    }

    @Override
    public String getGameInfo(int view) {
        //先清空棋盘
        curGrids = GridsUtils.copyGrids(originGrids);
        signList.clear();
        signList.add(cacheSign);
        pieceRender();
        if(selectedTarget!=null){
            signList.add(new AroundSign(getIndex(selectedTarget.pRow,selectedTarget.pCol), "#449F80F7", "#FF9F80F7", 1.0f));
            for(int i=0;i<curGrids.length;i++)
            for(int j=0;j<curGrids[0].length;j++)
                if(selectedTarget.canMove(this,i,j))
                    signList.add(new AroundSign(getIndex(i,j), "#449F80F7", "#FF9F80F7", 1.0f));
        }
        gameTip="黑方剩余"+ zeroRemainBlack +"个0\n白方剩余"+ zeroRemainWhite +"个0";
        return super.getGameInfo(view);
    }

    private void pieceRender(){
        for(int i=0;i<curGrids.length;i++)
        for(int j=0;j<curGrids[0].length;j++)
            curGrids[i][j]=0;
        for(Piece target:pieceList){
            if(!target.revealed) curGrids[target.pRow][target.pCol]=7;
            else{
                curGrids[target.pRow][target.pCol]=target.mSide;
                signList.add(new TextSign(this.getIndex(target.pRow,target.pCol),String.valueOf(target.rank),target.getColor()));
            }
        }
    }

    @Override
    protected void doStart(){
        DataManager.noticeAllGameStart(player_black, player_white, roomName);
        overFlag = 1;//重置结束状态：对弈进行中未结束
        playingStartTime = System.currentTimeMillis(); //重置对弈开始时间
        resetGrids();
        initPiece();
        selectedTarget=null;
        noticeFirstMove();
    }

    @Override
    public void doRule(int row, int col, int value, int view) {
        selectOrMove(this, row, col);
        getGameInfo();
        checkWin();
    }

    public void checkWin(){
        if(zeroRemainWhite==0)
            doOver(BLACK_WIN, player_black.getNickNameOrTemp() + "执黑棋战胜" + player_white.getNickNameOrTemp());
        if(zeroRemainBlack==0)
            doOver(WHITE_WIN, player_white.getNickNameOrTemp() + "执白棋战胜" + player_black.getNickNameOrTemp());
    }

    public void noticeFirstMove() {
        noticeBlackMove();
    }

    private void initPiece() {
        pieceList.clear();
        int swapIndex,swapTmp,indexTmp=0,x,y;
        int[] randSeq=new int[100];
        for(int i=0;i<100;i++) randSeq[i]=i;
        for(int i=99;i>0;i--){
            swapIndex=(int)Math.floor(Math.random()*(i+1));
            swapTmp=randSeq[i];
            randSeq[i]=randSeq[swapIndex];
            randSeq[swapIndex]=swapTmp;
        }
        int[] pieceCnt={4,4,6,6,6,6,6,4,4,4};
        for(int side=1;side<3;side++){
            for(int rank=0;rank<10;rank++){
                for(int j=0;j<pieceCnt[rank];j++){
                    x=(int)Math.floor(randSeq[indexTmp]/10);
                    y=randSeq[indexTmp]-x*10;
                    pieceList.add(new Piece(side,x,y,rank,false));
                    indexTmp++;
        }}}
        zeroRemainBlack=4;
        zeroRemainWhite=4;
    }

    public int edible(int atkRank,int defRank,int side){
        //返回0不可吃 1可吃 2同归于尽 3自杀
        if(defRank==0){
            //判断吃子的是不是当前方场上最小的棋子
            int minRank=9;
            for(Piece piece:pieceList){
                if(piece.mSide!=side || !piece.revealed || piece.rank==0) continue;
                minRank=Math.min(minRank,piece.rank);
            }
            if(minRank==atkRank) return 1;
            else return 0;
        }
        if(atkRank>=defRank){
            return (atkRank%defRank==0)?2:1;
        }else{
            return (defRank%atkRank==0)?2:3;
        }
    }

    public boolean nonInter(int rowS,int rowE,int colS,int colE){
        boolean flag=true;
        if(rowS==rowE){ //两枚棋子在同一排
            for(int j=colS+1;j<colE;j++)
                if(getPieceByPos(rowS,j)!=null){
                    flag=false; break;
                }
        }else{ //两枚棋子在同一列
            for(int i=rowS+1;i<rowE;i++)
                if(getPieceByPos(i,colS)!=null){
                    flag=false; break;
                }
        }
        return flag;
    }

    public class Piece {
        public int mSide,pRow,pCol,rank;
        public boolean revealed;

        public Piece(int mSide, int pRow, int pCol, int rank, boolean revealed){
            this.mSide = mSide;
            this.pRow = pRow;
            this.pCol = pCol;
            this.rank = rank;
            this.revealed=revealed;
        }

        public boolean canMove(NanaBaroccoBWRoom room,int targetRow, int targetCol) {
            if(targetRow==pRow && targetCol==pCol) return false;
            if(targetRow!=pRow && targetCol!=pCol) return false;
            if(targetRow<0||targetRow>=room.curGrids.length||targetCol<0||targetCol>=room.curGrids[0].length) return false;
            if(Math.abs(targetRow-pRow)+Math.abs(targetCol-pCol)>rank) return false;
            if(!nonInter(Math.min(pRow,targetRow),Math.max(pRow,targetRow),Math.min(pCol,targetCol),Math.max(pCol,targetCol)))
                return false;
            Piece enemy = room.getPieceByPos(targetRow, targetCol);
            if(enemy==null) return true;
            if(!enemy.revealed || enemy.mSide==mSide) return false;
            return edible(rank, enemy.rank, mSide)!=0;
        }

        protected String getColor(){return mSide==1?MoreColorCost.BLACK_CHESS_WORD:MoreColorCost.WHITE_CHESS_WORD;}
        public String info(){return String.format("%d-%d/%d", rank, pRow, pCol);}
        public void move(int row, int col){pRow=row;pCol=col;}
        public void reveal(){revealed=true;}
    }

    public Piece getPieceByPos(int row, int col) {
        for (Piece piece : pieceList)
            if (piece.pRow == row && piece.pCol == col)
                return piece;
        return null;
    }

    public void selectOrMove(NanaBaroccoBWRoom room, int row, int col) {
        Piece target = getPieceByPos(row, col);
        if (target == null && selectedTarget == null) return; //既没有点击棋子，又没有已选中的棋子
        if (selectedTarget == null){
            if(!target.revealed){ //翻棋子
                target.reveal();
                selectedTarget=null;
                noticeChangeMove();
            }else if(target.mSide==cur){ //选中棋子
                selectedTarget = target;
                noticeAllRefreshGameInfo();
            }
            return ;
        }
        if (selectedTarget == target){ //取消选中棋子
            selectedTarget = null;
            noticeAllRefreshGameInfo();
            return;
        }
        if(!selectedTarget.canMove(room,row,col)){ //不能走子，取消选中棋子
            selectedTarget = null;
            noticeAllRefreshGameInfo();
            return;
        }
        //走子逻辑
        Piece enemy = room.getPieceByPos(row,col);
        if(enemy==null)
            selectedTarget.move(row,col);
        else{
            int edibleState=edible(selectedTarget.rank,enemy.rank,selectedTarget.mSide);
            if(edibleState>1) pieceList.remove(selectedTarget);
            else selectedTarget.move(row,col);
            if(edibleState==1 || edibleState==2){
                if(enemy.rank==0)
                    if(enemy.mSide==1) zeroRemainBlack--;
                    else zeroRemainWhite--;
                pieceList.remove(enemy);
            }
        }
        selectedTarget = null;
        noticeChangeMove();
    }

    protected void noticeChangeMove() {
        selectedTarget=null;
        if(cur==1) noticeWhiteMove();
        else noticeBlackMove();
    }

}

